<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Acconeer API: Sparse Service</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">Acconeer API
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('sparse.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Sparse Service </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>The Sparse Service is one of four services that provides an interface for reading out the radar signal from the Acconeer A111 sensor. The data returned from the Sparse service can be used in different types of algorithms such as motion detection algorithms and presence detection. For basic distance measurements, Envelope service is a good starting point and the advanced users that needs phase information for detecting very small variations in distance will probably prefer the IQ data service instead of the Sparse service.</p>
<div class="image">
<img src="RSS_stack.png" alt="RSS_stack.png"/>
</div>
<p>Acconeer also provide several easy to use detectors that are implemented on top of the basic data services. The detectors provide APIs for higher level tasks. A detector utilizing Sparse service could be used for presence detection.</p>
<p>Acconeer provide an example of how to use the Sparse service: <a class="el" href="example__service__sparse_8c.html">example_service_sparse.c</a></p>
<p>The Sparse service is fundamentally different from the other services. Instead of sampling the reflected pulse several times per wavelength (which is ~5 mm), the pulse is sampled roughly every 60 mm. As such, the Sparse service should not be used to measure the reflections of static objects. Instead, the Sparse service produces a sequence of measurements of the sparsely located sampling points. This allows for detection of any movement, small or large, occurring in front of the sensor at the configured sampling points.</p>
<div class="image">
<img src="sparse_data.png" alt="sparse_data.png"/>
</div>
<p>The above image illustrates how a single sparse point samples a reflected pulse from a moving target. Due to the movements of the target, the signal from the Sparse service varies over time. If the object is static, the signal too will be static, but not necessarily zero.</p>
<p>Every data frame from the Sparse service consists of a configurable number of sweeps, which are sampled immediately after each other. Every sweep consists of one or several points sampled in space as configured. The sweeps are, for many applications, sampled closely enough in time that they can be regarded as being sampled simultaneously. In such applications, the sweeps can be averaged for optimal SNR. Note that unlike the other services, there is no pre-processing applied to the data. As pre-processing is not needed, this service is relatively computationally inexpensive.</p>
<p>The Sparse service is ideal for motion-sensing applications requiring low power consumption. Often, less processing is needed as the Sparse service outputs a lot less data than the Envelope or IQ service.</p>
<p>For more details on the Sparse data it is recommended to use our exploration tool. Check it out on <a href="https://github.com/acconeer/acconeer-python-exploration">github</a>, <a href="https://github.com/acconeer/acconeer-python-exploration">https://github.com/acconeer/acconeer-python-exploration</a>.</p>
<h2>Disclaimer</h2>
<p>Profile 3-5 will not have optimal performance using A111 with batch number 10467, 10457 or 10178 (also when mounted on XR111 and XR112). XM112 and XM122 are not affected since they have A111 from other batches.</p>
<h1>Setting up the Service</h1>
<h2>Initializing the System</h2>
<p>The Radar System Software (RSS) must be activated before any other calls are done to the radar sensor service API. The activation requires a pointer to an <a class="el" href="structacc__hal__t.html" title="This struct contains the information about the sensor integration that RSS needs. ...">acc_hal_t</a> struct which contains information on the hardware integration and function pointers to hardware driver functions that are needed by RSS. See chapter 4 in the document “HAL Integration User Guide” for more information on how to integrate to the driver layer and populate the hal struct.</p>
<p>In Acconeer’s example integration towards STM32 and the drivers generated by the STM32Cube tool, there is a function acc_hal_integration_get_implementation to obtain the hal struct.</p>
<div class="fragment"><div class="line"><a class="code" href="structacc__hal__t.html">acc_hal_t</a> hal = <a class="code" href="acc__hal__integration_8h.html#a8b93eb4abdb9ad75250ca6404e0b412d">acc_hal_integration_get_implementation</a>();</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="group__RSS.html#ga478a45b4920777d3d4fc0f5fc8d05b58">acc_rss_activate</a>(&amp;hal))</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><p>The corresponding code looks slightly different in software packages for the Raspberry Pi and other software packages from Acconeer where peripheral drivers for the host are included. The driver layer is first initialized by calling acc_driver_hal_init. The hal struct is then obtained with the function acc_driver_hal_get_implementation.</p>
<div class="fragment"><div class="line"><span class="keywordflow">if</span> (!acc_driver_hal_init())</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div><div class="line"></div><div class="line">hal = acc_driver_hal_get_implementation();</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="group__RSS.html#ga478a45b4920777d3d4fc0f5fc8d05b58">acc_rss_activate</a>(&amp;hal))</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><h2>Service API</h2>
<p>All services in the Acconeer API are created and activated in two distinct steps. In the first creation step the configuration settings are evaluated and all necessary resources are allocated. If there is some error in the configuration or if there are not enough resources in the system to run the service, the creation step will fail. However, when the creation is successful you can be sure that the second activation step will not fail due to any configuration or resource issues. When the service is activated the radar is activated and the radar data starts to flow from the sensor to the application.</p>
<h2>Sparse Service Configuration</h2>
<p>Before the Sparse service can be created and activated, we must prepare a service configuration. First a configuration is created.</p>
<div class="fragment"><div class="line"><a class="code" href="group__Generic.html#ga3659144b760468217ed4cb1fc3447330">acc_service_configuration_t</a> sparse_configuration = <a class="code" href="group__Sparse.html#ga0c167644d28b71ebd618b63ac45907b7">acc_service_sparse_configuration_create</a>();</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (sparse_configuration == NULL)</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><p>The newly created service configuration contains default settings for all configuration parameters and can be passed directly to the acc_service_create function. However, in most scenarios there is a need to change at least some of the configuration parameters. See <a class="el" href="acc__service__sparse_8h.html">acc_service_sparse.h</a> and <a class="el" href="acc__base__configuration_8h.html">acc_base_configuration.h</a> for a complete description of configuration parameters.</p>
<h3>Profiles</h3>
<p>The services and detectors support profiles with different configuration of emission in the sensor. The different profiles provide an option to configure the wavelet length and optimize on either depth resolution or radar loop gain. More information regarding profiles can be read in the <a href="https://acconeer-python-exploration.readthedocs.io/en/latest/sensor_introduction.html">sensor introduction document</a>, <a href="https://acconeer-python-exploration.readthedocs.io/en/latest/sensor_introduction.html">https://acconeer-python-exploration.readthedocs.io/en/latest/sensor_introduction.html</a>.</p>
<p>The Sparse service supports 5 different profiles which are defined in <a class="el" href="acc__service_8h.html">acc_service.h</a>. Profile 1 has the shortest wavelet and should be used in applications which aim to see multiple objects or with short distance to the object. Profiles with higher numbers hve longer wavelet and are more suitable to use in applications which aim to see objects with weak reflection or objects further away from the sensor. The highest profiles, 4 and 5, are optimized for maximum radar loop gain which leads to lower precision in the distance estimate.</p>
<p>Profiles can be configured by the application by using a set function in the service api. The default profile is ACC_SERVICE_PROFILE_2.</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> <a class="code" href="group__Generic.html#gad3791b1f05c041be251aedbbf6e4756f">acc_service_profile_set</a>(<a class="code" href="group__Generic.html#ga3659144b760468217ed4cb1fc3447330">acc_service_configuration_t</a> service_configuration,</div><div class="line">                             <a class="code" href="group__Generic.html#gaa281da2c8fcd709b60cfdfe2b75b888a">acc_service_profile_t</a>       profile);</div></div><!-- fragment --><h3>Repetition Mode</h3>
<p>RSS supports two different repetition modes which configure the control flow of the sensor when it's producing data. In both modes, the application initiates the data transfer from the sensor and is responsible to keep the timing by fetching data from the service. The repetition modes are called on_demand and streaming and the default mode is on_demand.</p>
<p>Repetition mode on_demand lets the application decide when the sensor produces data. This mode is recommended to be used if the application is not dependent of a fixed update rate and it's more important for the application to control the timing. An example could be if the application requests data at irregular time or with low frequency and it's more important to enable low power consumption. Repetition mode on_demand should also be used if the application set a length which requires stitching or want to use power save mode off.</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> <a class="code" href="group__Base.html#gaf0300d0b678002ee5298c6ce0af04cf9">acc_base_configuration_repetition_mode_on_demand_set</a>(<a class="code" href="group__Base.html#gacaedd5eecda28ac996abb8ff9e872c30">acc_base_configuration_t</a> configuration);</div></div><!-- fragment --><p>Repetition mode streaming configures the sensor to produce data based on a hardware timer which is very accurate. It is recommended to use repetition mode streaming if the application requires very accurate timing. An example could be if the data should be processed with a fft. This mode can not be used it the application set a length which requires stitching.</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> <a class="code" href="group__Base.html#ga724423ab3347405e165a2f844eb2924d">acc_base_configuration_repetition_mode_streaming_set</a>(<a class="code" href="group__Base.html#gacaedd5eecda28ac996abb8ff9e872c30">acc_base_configuration_t</a> configuration, <span class="keywordtype">float</span> update_rate);</div></div><!-- fragment --><h2>Creating Service</h2>
<p>After the Sparse configuration has been prepared and populated with desired configuration parameters, the actual Sparse service instance must be created. During the creation step all configuration parameters are validated and the resources needed by RSS are reserved. This means that if the creation step is successful, we can be sure that it is possible to activate the service and get data from the sensor (unless there is some unexpected hardware error).</p>
<div class="fragment"><div class="line"><a class="code" href="group__Generic.html#gac31f87097f46e587c8d54fb0406f62d4">acc_service_handle_t</a> handle = <a class="code" href="group__Generic.html#ga165f40004fae21f84757a839f7253db0">acc_service_create</a>(sparse_configuration);</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (handle == NULL)</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><p>During service create, the service run a calibration sequence on the sensor. The calibration is used once at create and can be used until the service is destroyed. A new calibration is needed if the environment is changed, such as deviation in temperature.</p>
<p>If the service handle returned from acc_service_create is equal to NULL, then some setting in the configuration made it impossible for the system to create the service. One common reason is that the requested sweep length is too long or if the calibration fail, but in general, looking for error messages in the log is the best way to find out why a service creation failed.</p>
<p>When the service has been created it is possible to get the actual number of samples (data_length) we will get for each frame. This value can be useful when allocating buffers for storing the Sparse data.</p>
<div class="fragment"><div class="line"><a class="code" href="structacc__service__sparse__metadata__t.html">acc_service_sparse_metadata_t</a> sparse_metadata;</div><div class="line"><a class="code" href="group__Sparse.html#gab5605ff524cc6e66604a3d7b0f7c94fb">acc_service_sparse_get_metadata</a>(handle, &amp;sparse_metadata);</div><div class="line"></div><div class="line">uint16_t data[sparse_metadata.<a class="code" href="structacc__service__sparse__metadata__t.html#a3067a08467b638d8a6f7c5040c65c1bf">data_length</a>];</div></div><!-- fragment --><p>It is now also possible to activate the service. This means that the radar sensor starts to do measurements.</p>
<div class="fragment"><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="group__Generic.html#ga35f20ca785726b4c1c7aacf46c46cf39">acc_service_activate</a>(handle))</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><h2>Reading Sparse Data from the Sensor</h2>
<p>Sparse data is read from the sensor by a call to the function acc_service_sparse_get_next. This function blocks until the next sweep arrives from the sensor and the Sparse data is then copied to the Sparse data array.</p>
<div class="fragment"><div class="line">uint16_t                           data[sparse_metadata.<a class="code" href="structacc__service__sparse__metadata__t.html#a3067a08467b638d8a6f7c5040c65c1bf">data_length</a>];</div><div class="line"><a class="code" href="structacc__service__sparse__result__info__t.html">acc_service_sparse_result_info_t</a> result_info;</div><div class="line"></div><div class="line"><span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; 10; i++)</div><div class="line">{</div><div class="line">        <span class="keywordflow">if</span> (!<a class="code" href="group__Sparse.html#gac7ba1b4bd10ecf1f581ff8e59012a970">acc_service_sparse_get_next</a>(handle, data, sparse_metadata.<a class="code" href="structacc__service__sparse__metadata__t.html#a3067a08467b638d8a6f7c5040c65c1bf">data_length</a>, &amp;result_info))</div><div class="line">        {</div><div class="line">                <span class="comment">/* Handle error */</span></div><div class="line">        }</div><div class="line">}</div></div><!-- fragment --><h2>Deactivating and Destroying the Service</h2>
<p>Call the acc_service_deactivate function to stop measurements.</p>
<div class="fragment"><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="group__Generic.html#gaa1b126a55a9defe0d7baff5d7890435f">acc_service_deactivate</a>(handle))</div><div class="line">{</div><div class="line">        <span class="comment">/* Handle error */</span></div><div class="line">}</div></div><!-- fragment --><p>After the service has been deactivated it can be activated again to resume measurements or it can be destroyed to free up the resources associated with the service handle.</p>
<div class="fragment"><div class="line"><a class="code" href="group__Generic.html#gad7cc3154b0227e63d18b11aa672de3af">acc_service_destroy</a>(&amp;handle);</div></div><!-- fragment --><p>Finally, call acc_rss_deactivate when the application doesn’t need to access the Radar System Software anymore. This releases any remaining resources allocated in RSS.</p>
<div class="fragment"><div class="line"><a class="code" href="group__RSS.html#ga5221ed13d3d7aff540420aacfe55b5e2">acc_rss_deactivate</a>();</div></div><!-- fragment --><h1>How to Interpret the Sparse Data</h1>
<p>The data frame from the Sparse Service should be interpreted as a one-dimensional array with the number of sweeps stored consecutively. The first datapoint in each sweep corresponds radar signal at distance start_m (see Sect. 6.1) and the last data point to distance start_m + length_m. The data points between correspond to the radar signal between these to distances, sampled approximately 60 mm apart and exact number is given by metadata, step_length.</p>
<p>The data format is unsigned 16 bits integer and the data is centered around approximately 32000, but the center level can differ slightly between sensors.</p>
<p>The sweeps are acquired during a relatively short time, so for objects moving with low speed, such as humans sitting or standing, the sweeps should be very similar, deviating from each other only by sensor noise.</p>
<p>In the figure below the data in a data frame from the Sparse service is plotted. The scanned range is 1 meter resulting in 17 data points (1 meter divided by 60 mm is rounded to 17). The range is scanned 16 times resulting in 272 data points. So, index 0, 17, 34, 51, etc. corresponds to measurement of the closest distance, i.e. “start”, and index 16, 33, 50, 67, etc. corresponds to measurements of the farthest distance, i.e. “start + length”. The points in between correspond to measurements of the point in between in range, similar to the IQ and Envelope service.</p>
<p>In the center of the range a reflector is present which give rise to the deviation from the mean data level at the center of each sweep. Also, the difference between each sweep in the data frame is very low, suggesting a stationary reflector.</p>
<p>Below is an example Sparse data frame. Here, each sweep consists of 17 measured distances and there is 16 sweeps in the data frame. The first data point in each sweep is marked in light blue.</p>
<div class="image">
<img src="sparse_data2.png" alt="sparse_data2.png"/>
</div>
<h2>Sparse Metadata</h2>
<p>In addition to the array with Sparse data samples, a metadata data structure provides side information that can be useful when interpreting the Sparse data. This metadata can be retrieved after creating the service. It will not change during operation, so it is only needed to be retrieved once for the created service.</p>
<div class="fragment"><div class="line"><a class="code" href="structacc__service__sparse__metadata__t.html">acc_service_sparse_metadata_t</a> sparse_metadata;</div><div class="line"><a class="code" href="group__Sparse.html#gab5605ff524cc6e66604a3d7b0f7c94fb">acc_service_sparse_get_metadata</a>(handle, &amp;sparse_metadata);</div></div><!-- fragment --><p>The most important member variable in the meta data structure is data_length which holds the length of the Sparse data array. For other member variables see <a class="el" href="structacc__service__sparse__metadata__t.html" title="Metadata for the sparse service. ">acc_service_sparse_metadata_t</a>.</p>
<h2>Sparse Result Info</h2>
<p>Result info is another kind of metadata which might change for each retrieved result. Result info is provided at the same time as the resulting array, either when calling get_next() or when a callback is triggered.</p>
<div class="fragment"><div class="line"><a class="code" href="structacc__service__sparse__result__info__t.html">acc_service_sparse_result_info_t</a> result_info;</div><div class="line"><a class="code" href="group__Sparse.html#gac7ba1b4bd10ecf1f581ff8e59012a970">acc_service_sparse_get_next</a>(handle, data, data_length, &amp;result_info);</div></div><!-- fragment --><p>The most important member variable is the sensor_communication_error which indicates whether a sensor communication has occurred. For other member variables see <a class="el" href="structacc__service__sparse__result__info__t.html" title="Metadata for each result provided by the sparse service. ">acc_service_sparse_result_info_t</a> </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="md__home_ai_jenkins_workspace_sw-main_0D2_doc_user_guides_rss_user_guide_main.html">User guides</a></li>
    <li class="footer">Generated on Mon Dec 2 2019 09:40:46 for Acconeer API by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.13 </li>
  </ul>
</div>
</body>
</html>
